home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / nihcl-30.lha / nihcl-3.0 / lib / Bag.c < prev    next >
C/C++ Source or Header  |  1990-05-19  |  5KB  |  253 lines

  1. /* Bag.c -- implementation of a Set of Objects with possible duplicates
  2.  
  3.     THIS SOFTWARE FITS THE DESCRIPTION IN THE U.S. COPYRIGHT ACT OF A
  4.     "UNITED STATES GOVERNMENT WORK".  IT WAS WRITTEN AS A PART OF THE
  5.     AUTHOR'S OFFICIAL DUTIES AS A GOVERNMENT EMPLOYEE.  THIS MEANS IT
  6.     CANNOT BE COPYRIGHTED.  THIS SOFTWARE IS FREELY AVAILABLE TO THE
  7.     PUBLIC FOR USE WITHOUT A COPYRIGHT NOTICE, AND THERE ARE NO
  8.     RESTRICTIONS ON ITS USE, NOW OR SUBSEQUENTLY.
  9.  
  10. Author:
  11.     K. E. Gorlen
  12.     Bg. 12A, Rm. 2033
  13.     Computer Systems Laboratory
  14.     Division of Computer Research and Technology
  15.     National Institutes of Health
  16.     Bethesda, Maryland 20892
  17.     Phone: (301) 496-1111
  18.     uucp: uunet!nih-csl!kgorlen
  19.     Internet: kgorlen@alw.nih.gov
  20.     September, 1985
  21.  
  22. Function:
  23.     
  24. A Bag is like a Set, except Bags can contain multiple occurrences of
  25. equal objects.  Bags are implemented by using a Dictionary to associate
  26. each object in the Bag with its number of occurrences.
  27.  
  28. $Log:    Bag.c,v $
  29.  * Revision 3.0  90/05/20  00:19:06  kgorlen
  30.  * Release for 1st edition.
  31.  * 
  32. */
  33.  
  34. #include "Bag.h"
  35. #include "AssocInt.h"
  36. #include "Integer.h"
  37. #include "nihclIO.h"
  38.  
  39. #define    THIS    Bag
  40. #define    BASE    Collection
  41. #define BASE_CLASSES BASE::desc()
  42. #define MEMBER_CLASSES Dictionary::desc()
  43. #define VIRTUAL_BASE_CLASSES
  44.  
  45. DEFINE_CLASS(Bag,1,"$Header: /afs/alw.nih.gov/unix/sun4_40c/usr/local/src/nihcl-3.0/share/lib/RCS/Bag.c,v 3.0 90/05/20 00:19:06 kgorlen Rel $",NULL,NULL);
  46.  
  47. extern const int NIHCL_REMOVEERR;
  48.  
  49. Bag::Bag(unsigned size) : contents(size)
  50. {
  51.     count = 0;
  52. }
  53.  
  54. Bag::Bag(const Bag& b) : contents(b.contents)
  55. {
  56.     count = b.count;
  57.     Object* a;
  58.     Iterator i(contents);
  59.     while (a = i++) contents.at(i.index-1) = a->shallowCopy();
  60. }
  61.  
  62. Bag::~Bag()
  63. {
  64.     DO(contents,AssocInt,a) delete a; OD;
  65. }
  66.  
  67. void Bag::operator=(const Bag& b)
  68. {
  69.     if (this == &b) return;
  70.     DO(contents,AssocInt,a) delete a; OD;
  71.     contents = b.contents;
  72.     count = b.count;
  73.     Object* a;
  74.     Iterator i(contents);
  75.     while (a = i++) contents.at(i.index-1) = a->shallowCopy();
  76. }
  77.     
  78. void Bag::reSize(unsigned newSize)
  79. {
  80.     contents.reSize(newSize);
  81. }
  82.  
  83. Object* Bag::addWithOccurrences(Object& ob, unsigned n)
  84. {
  85.     AssocInt* a = (AssocInt*)contents.assocAt(ob);
  86.     Object* o = &ob;
  87.     if (a == 0) {
  88.             a = new AssocInt(ob,n);
  89.         contents.add(*a);
  90.     }
  91.     else {
  92.         Integer& i = *Integer::castdown(a->value());
  93.         o = a->key();
  94.         i.value(i.value()+n);
  95.     }
  96.     count += n;
  97.     return o;
  98. }
  99.  
  100. Object* Bag::add(Object& ob)
  101. {
  102.     return addWithOccurrences(ob,1);
  103. }
  104.  
  105. Object*& Bag::at(int i)                    { return contents.at(i); }
  106.  
  107. const Object *const& Bag::at(int i) const    { return contents.at(i); }
  108.  
  109. unsigned Bag::capacity() const { return contents.capacity(); }
  110.  
  111. void Bag::deepenShallowCopy()
  112. {
  113.     BASE::deepenShallowCopy();
  114.     contents.deepenShallowCopy();
  115. }
  116.  
  117. Object* Bag::doNext(Iterator& pos) const
  118. {
  119.     const AssocInt* a;
  120.     while (YES) {
  121.         if (pos.num == 0) {
  122.             a = AssocInt::castdown(contents.doNext(pos));
  123.             if (a == NULL) return NULL;
  124.         }
  125.         else a = AssocInt::castdown(contents.at(pos.index-1));
  126.         if (pos.num++ < (Integer::castdown(a->value()))->value())
  127.             return a->key();
  128.         pos.num = 0;
  129.     }
  130. }
  131.  
  132. void Bag::dumpOn(ostream& strm) const
  133. {
  134.     strm << className() << '[';
  135.     DO(contents,AssocInt,a) a->dumpOn(strm); OD
  136.     strm << "]\n";
  137. }
  138.  
  139. Object* Bag::remove(const Object& ob)
  140. {
  141.     AssocInt* a = (AssocInt*)contents.assocAt(ob);
  142.     Object* rob = 0;        // return NULL until last occurrence removed
  143.     if (a == 0) setError(NIHCL_REMOVEERR,DEFAULT,this,className(),ob.className(),&ob);
  144.     Integer* i = Integer::castdown(a->value());
  145.     unsigned n = (unsigned)(i->value());
  146.     if (--n == 0) {
  147.         rob = a->key();
  148.         delete AssocInt::castdown(contents.remove(*a));
  149.     }
  150.     else i->value(n);
  151.     --count;
  152.     return rob;
  153. }
  154.  
  155. void Bag::removeAll()
  156. {
  157.     DO(contents,AssocInt,a) delete a; OD;
  158.     contents.removeAll();
  159.     count = 0;
  160. }
  161.  
  162. bool Bag::operator==(const Bag& b) const
  163. {
  164.     return count==b.count && contents==b.contents;
  165. }
  166.  
  167. unsigned Bag::hash() const    { return count^contents.hash(); }
  168.  
  169. bool Bag::isEqual(const Object& p) const
  170. {
  171.     return p.isSpecies(classDesc) && *this==castdown(p);
  172. }
  173.  
  174. const Class* Bag::species() const { return &classDesc; }
  175.  
  176. unsigned Bag::occurrencesOf(const Object& ob) const
  177. {
  178.     AssocInt* a = (AssocInt*)contents.assocAt(ob);
  179.     if (a == 0) return 0;
  180.     else return (Integer::castdown(a->value()))->value();
  181. }
  182.  
  183. unsigned Bag::size() const    { return count; }
  184.  
  185. Bag Collection::asBag() const
  186. {
  187.     Bag cltn(MAX(size(),DEFAULT_CAPACITY));
  188.     addContentsTo(cltn);
  189.     return cltn;
  190. }
  191.  
  192. static unsigned bag_capacity;
  193.  
  194. Bag::Bag(OIOin& strm)
  195. :
  196. #ifdef MI
  197.     Object(strm),
  198. #endif
  199.     BASE(strm),
  200.     contents((strm >> bag_capacity, bag_capacity))
  201. {
  202.     count = 0;
  203.     unsigned i,n;
  204.     strm >> n;        // read bag size 
  205.     while (n--) {
  206.         strm >> i;
  207.         addWithOccurrences(*Object::readFrom(strm),i);
  208.     }
  209. }
  210.  
  211. void Bag::storer(OIOout& strm) const
  212. {
  213.     BASE::storer(strm);
  214.     strm << contents.capacity() << contents.size();
  215.     DO(contents,AssocInt,a)
  216.         strm << (Integer::castdown(a->value()))->value();
  217.         (a->key())->storeOn(strm);
  218.     OD
  219. }
  220.  
  221. Bag::Bag(OIOifd& fd)
  222. :
  223. #ifdef MI
  224.     Object(fd),
  225. #endif
  226.     BASE(fd),
  227.     contents((fd >> bag_capacity, bag_capacity))
  228. {
  229.     count = 0;
  230.     unsigned i,n;
  231.     fd >> n;
  232.     while ( n-- ) {
  233.         fd >> i;
  234.         addWithOccurrences(*Object::readFrom(fd),i);
  235.     }
  236. }
  237.  
  238. void Bag::storer(OIOofd& fd) const
  239. {
  240.     BASE::storer(fd);
  241.     fd << contents.capacity() << contents.size();
  242.     DO(contents,AssocInt,a)
  243.         fd << (Integer::castdown(a->value()))->value();
  244.         (a->key())->storeOn(fd);
  245.     OD
  246. }
  247.  
  248. int Bag::compare(const Object&) const
  249. {
  250.     shouldNotImplement("compare");
  251.     return 0;
  252. }
  253.